/*
 * @(#) $Header$
 *
 * Copyright (C) 2010  Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.baselib.io;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

/**
 * Class {@code PathUtil} provides methods to manipulate file paths.
 *
 * @author <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.baselib.io.PathUtil">Daniel Léonard</a>
 * @version $Revision$
 * @see   <a href="http://msdn.microsoft.com/en-us/library/beth2052%28v=VS.90%29.aspx">Path Methods (System.IO - msdn.microsoft.com)</a>
 */
public class PathUtil {

//---------------------------
// Constructors
//---------------------------

   /**
    * Constructor.
    */
   protected PathUtil() {
   // nothing
      }


//---------------------------
// Class methods
//---------------------------

   /**
    * Combines multiple names to form a single path.
    * @param   paths  the names
    * @return   a path
    */
   public static String combine(String... paths) {
      StringBuilder sb = new StringBuilder();

      int len = paths.length;
      if (0 != len) {
         sb.append(paths[0]);
         }

      String separator = File.separator;
      for (int i = 1; i < len; i++) {
         sb.append(separator).append(paths[i]);
         }

      String path = sb.toString();
      return path;
      }

   /**
    * Combines multiple files to form a single path.
    * @param   files  the files
    * @return   a path
    */
   public static File combine(File... files) {
      int len = files.length;

      String[] paths = new String[len];
      for (int i = 0; i < len; i++) {
         File file = files[i];
         String path = file.getPath();
         paths[i] = path;
         }
      String path = PathUtil.combine(paths);

      File file = new File(path);
      return file;
      }

   /**
    * Combines multiple files and names to form a single path.
    * @param   base  the base directory
    * @param   names  the path from the base directory
    * @return   a path
    */
   public static File combine(File base, String... names) {
      int len = names.length + 1;
      String[] paths = new String[len];

      paths[0] = base.getPath();

      for (int i = 1; i < len; i++) {
         String path = names[i - 1];
         paths[i] = path;
         }
      String path = PathUtil.combine(paths);

      File file = new File(path);
      return file;
      }


   /**
    * Splits the filename into the names of the components making the path using
    * the {@code File#getName()} method. The name of the first component is
    * often the empty string, please see the document of {@link File#getName()}.
    *
    * <pre>
    *    String filename = "C:/Program Files (x86)/World of Warcraft/Interface/AddOns";
    *    String[] names = PathUtil.split(filename);
    *    assert "".equals(names[0]);
    *    assert "Program Files (x86)".equals(names[1]);
    *    assert "World of Warcraft".equals(names[2]);
    *    assert "Interface".equals(names[3]);
    *    assert "AddOns".equals(names[4]);
    * </pre>
    * @param   filename   the filename to split.
    * @return   the names of the files making the path.
    * @see   #split(File)
    * @see   File#getName()
    */
   public static String[] split(String filename) {
      File[] files = split(new File(filename));

      int len = files.length;
      String[] filenames = new String[len];
      for (int i = 0; i < len; i++) {
         File file = files[i];
         String name = file.getName();
         filenames[i] = name;
         }

      return filenames;
      }

   /**
    * Splits the file into its file components.
    * @param   file   the file to split.
    * @return   the files making up the path.
    */
   public static File[] split(File file) {
      List<File> list = new LinkedList<>();

      for (File parent = file; null != parent; parent = parent.getParentFile()) {
         list.add(0, parent);
         }

      File[] files = list.toArray(new File[0]);
      return files;
      }


   /**
    * Creates the directory structure described by the given path.
    * @param   paths   the directory to create.
    * @return   {@code true} if all the directories were created,
    *           {@code false} otherwise.
    * @see   #combine(String...)
    * @see   #mkdir(File)
    */
   public static boolean mkdir(String... paths) {
      String path = combine(paths);
      File directory = new File(path);
      boolean success = mkdir(directory);
      return success;
      }

   /**
    * Creates the directory structure described by the given path.
    * @param   files   the directory to create.
    * @return   {@code true} if all the directories were created,
    *           {@code false} otherwise.
    * @see   #combine(File...)
    * @see   #mkdir(File)
    */
   public static boolean mkdir(File... files) {
      File directory = combine(files);
      boolean success = mkdir(directory);
      return success;
      }

   /**
    * Creates the directory structure described by the given path.
    * @param   base  the base directory
    * @param   names  the path from the base directory
    * @return   {@code true} if all the directories were created,
    *           {@code false} otherwise.
    * @see   #combine(File, String...)
    * @see   #mkdir(File)
    */
   public static boolean mkdir(File base, String... names) {
      File directory = combine(base, names);
      boolean success = mkdir(directory);
      return success;
      }

   /**
    * Creates the directory structure described by the given file object.
    * @param   directory   the directory to create.
    * @return   {@code true} if all the directories were created,
    *           {@code false} otherwise.
    * @see   File#mkdirs()
    */
   public static boolean mkdir(File directory) {
      boolean success = directory.mkdirs();
      return success;
      }

// TODO : do a delete directory. should it delete all the files and everything or try to delete the directory iff empty?

   }
